﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ThreeByte.ActiveDeck;
using System.Xml.Linq;
using ThreeByte.ActiveDeck.Publish.Model;
using ThreeByte.ActiveDeck.Publisher.Client;
using System.Net;
using ThreeByte.ActiveDeck.Service;
using System.Text.RegularExpressions;

namespace ActiveUpdate_Test_Client
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
#if DEBUG
        private static readonly string SYNC_HOST = @"https://127.0.0.1:444/Sync.svc";
#else
        private static readonly string SYNC_HOST = @"https://svc.activedeck.com/Sync.svc";
#endif
        ActivePublisherClient _client;
        private object _clientLock = new object();

        private NetworkCredential Credential = AuthorizationUtil.ANONYMOUS; //Good Default
        private bool newCredential = false;

        public MainWindow() {
            InitializeComponent();

            _client = new ActivePublisherClient(SYNC_HOST, Credential);
        }

        private void VerifyClient() {
            if(!newCredential) {
                return;
            }
            lock(_clientLock) {
                _client.UnsubscribeAll();
                _client = new ActivePublisherClient(SYNC_HOST, Credential);
            }
        }


        private void SubscribeButton_Click(object sender, RoutedEventArgs e) {

            Output.Text = string.Empty;

            int fromInt = 0;
            int.TryParse(SubscribeFromText.Text, out fromInt);

            Subscription sub = new Subscription() {
                Channel = SubscribeChannelText.Text,
                From = fromInt,
                OnMessageReceived = OnMessage,
                OnError = OnError
            };
            lock(_clientLock) {
                _client.UnsubscribeAll();
                _client.SubscribeAsync(sub);
            }
        }

        private void OnMessage(Subscription sub, ActiveMessage message) {

            Console.WriteLine("Received Message");
            Dispatcher.BeginInvoke((Action)delegate() {
                Output.Text = message.Body.ToString();
            }, null);
            lock(_clientLock) {
                _client.SubscribeAsync(sub);
            }
        }

        private void OnError(Subscription sub, Exception ex) {

            Dispatcher.BeginInvoke((Action)delegate() {
                Output.Text = string.Format("Exception: [{0}]", ex);
            }, null);
            lock(_clientLock) {
                //Restart the subscription
                _client.SubscribeAsync(sub);
            }
        }

        private void PublishButton_Click(object sender, RoutedEventArgs e) {
            PublishResponseText.Text = string.Empty;

            ActiveMessage newMessage = new ActiveMessage() {
                Body = new XElement("Data", PublishText.Text),
                Channel = PublishChannelText.Text
            };

            lock(_clientLock) {
                _client.PublishAsync(newMessage, OnSuccess, OnError);
            }
        }

        void OnSuccess(ActiveMessage message) {
            Dispatcher.Invoke((Action)delegate() {
                PublishResponseText.Text = string.Format("{0}", message.Body);
            }, null);

        }

        void OnError(ActiveMessage message, Exception ex) {

            Dispatcher.Invoke((Action)delegate() {
                PublishResponseText.Text = string.Format("{0}\nException: [{1}]", message.Body, ex);
            }, null);
        }

        private void PresenterPasswordTextBox_PasswordChanged(object sender, RoutedEventArgs e) {
            HidePasswordIcon();
        }

        private void HidePasswordIcon() {
            GoodPasswordIcon.Visibility = Visibility.Hidden;
            BadPasswordIcon.Visibility = Visibility.Hidden;
            PasswordErrorIcon.Visibility = Visibility.Hidden;
            PasswordErrorIcon.ToolTip = null;
        }

        private void PresenterPasswordTextBox_PreviewKeyDown(object sender, KeyEventArgs e) {
            if(e.Key == Key.Enter || e.Key == Key.Return) {
                TestLogin_Click(null, null);
            }
        }

        private void TestLogin_Click(object sender, RoutedEventArgs e) {
            NetworkCredential newCred = new NetworkCredential(UserNameTextBox.Text, PresenterPasswordTextBox.SecurePassword);
            Credential = newCred;
            newCredential = true;
            VerifyClient();

            HidePasswordIcon();

            WebServiceClient client = new WebServiceClient(newCred);

            try {
                bool result = client.TestLogin();

                if(result) {
                    GoodPasswordIcon.Visibility = Visibility.Visible;
                } else {
                    BadPasswordIcon.Visibility = Visibility.Visible;
                }
            } catch(Exception ex) {
                PasswordErrorIcon.Visibility = Visibility.Visible;
                PasswordErrorIcon.ToolTip = ex.Message;
            }
        }

        private void Hyperlink_Click(object sender, RoutedEventArgs e) {

        }

        private void GetChannelsButton_Click(object sender, RoutedEventArgs e) {
            //Get the current channel listing
            lock(_clientLock) {
                try {
                    Dictionary<string, int> channels = _client.GetChannels(ChannelFilter.Text);

                    List<ActiveChannel> activeChannels = new List<ActiveChannel>();
                    foreach(string c in channels.Keys) {
                        activeChannels.Add(new ActiveChannel(c, channels[c]));
                    }
                    ChannelListBox.ItemsSource = activeChannels;

                } catch(Exception ex) {
                    Console.WriteLine("Could not retrieve channels");

                }
            }

        }

        private void ChannelFilter_TextChanged(object sender, TextChangedEventArgs e) {
            string presPattern = @"(\d+)_.+";
            if(PublishChannelText == null) {
                return;
            }

            Match m = Regex.Match(PublishChannelText.Text, presPattern);

            if(m.Success) {
                string newText = PublishChannelText.Text.Replace(m.Groups[1].Value, string.Empty);
                PublishChannelText.Text = string.Format("{0}{1}", ChannelFilter.Text, newText);
            } else {
                PublishChannelText.Text = string.Format("{0}_0", ChannelFilter.Text);
            }

        }

        private void ChannelListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            ActiveChannel channel = ChannelListBox.SelectedItem as ActiveChannel;
            if(channel == null) {
                return;
            }

            SubscribeChannelText.Text = channel.ID;
            SubscribeFromText.Text = string.Format("{0}", channel.LastMessage);
        }

    }
}
